package com.ayg.test.apitest.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ClassFinder {

    private static final Logger logger = LoggerFactory.getLogger(ClassFinder.class);
    static ClassLoader classloader = Thread.currentThread().getContextClassLoader();  
    /** 
     * 获取同一路径下所有子类或接口实现类 
     *  
     * @param
     * @return 
     * @throws IOException 
     * @throws ClassNotFoundException 
     */  
    public static List<Class<?>> getAllAssignedClass(Class<?> cls) {  
        List<Class<?>> classes = new ArrayList<>();
        for (Class<?> c : getClasses(cls)) {  
            if (cls.isAssignableFrom(c) && !cls.equals(c)) {  
                classes.add(c);  
            }  
        }  
        return classes;  
    }  
  
    /** 
     * 取得当前类路径下的所有类 
     *  
     * @param cls 
     * @return 
     * @throws IOException 
     * @throws ClassNotFoundException 
     */  
    public static List<Class<?>> getClasses(Class<?> cls) {  
        String pk = cls.getPackage().getName();  
        String path = pk.replace('.', '/');
        logger.info("预处理方法所在类路径：{}",path);
         //URL url = classloader.getResource(path);
        // return getClasses(new File(url.getFile()), pk);/*pk*/
        //de ClassFinder.class.getProtectionDomain().getCodeSource().getLocation().getPath();
      try {
            String dirPath = URLDecoder.decode(classloader.getResource(path).getPath(),"utf-8");

          // 打成jar包是读取
            dirPath = dirPath.replace("file:","");
            logger.info("预处理方法路径：{}",dirPath);
            return getClassInJar(new JarFile(dirPath.substring(0,dirPath.indexOf('!'))), path);
		} catch (UnsupportedEncodingException e) {
          logger.error("content:{}",e);
		} catch (IOException e) {
          logger.error("content:{}",e);
      }
        return new ArrayList<>();
    }  
  
    /** 
     * 迭代查找类 
     *  
     * @param dir 
     * @param pk 
     * @return 
     * @throws ClassNotFoundException 
     */  
    private static List<Class<?>> getClasses(File dir, String pk) {  
        List<Class<?>> classes = new ArrayList<>();
        if (!dir.exists()) {  
            return classes;  
        }  
        for (File f : dir.listFiles()) {  
            if (f.isDirectory()) {  
                classes.addAll(getClasses(f, pk + "." + f.getName()));  
            }  
            String name = f.getName();  
            if (name.endsWith(".class")) {  
            	try{
                classes.add(Class.forName(pk + "." + name.substring(0, name.length() - 6)));
                }catch(Exception ex){
                    logger.error("content:{}",ex);
                }
            }  
        }  
        return classes;  
    }

    public static List<Class<?>> getClassInJar(JarFile jarFile,String pk){
        List<Class<?>> classes = new ArrayList<>();
        Enumeration<JarEntry> entries = jarFile.entries();
        while (entries.hasMoreElements()) {
            JarEntry jarEntry = entries.nextElement();
            String innerpath = jarEntry.getName();
            if(innerpath.startsWith(pk) && innerpath.endsWith(".class") ){
                String path = innerpath.replace('/', '.');
                try{
                    classes.add(Class.forName(path.substring(0, path.length() - 6)));
                }catch(Exception ex){
                    logger.error("content:{}",ex);
                }
            }
        }
        return classes;

    }
}  